using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Data.SqlClient;
using System.IO;
using System.Collections;
using Microsoft.Win32;

namespace LoadTestController
{
    class WorkflowInfo
    {
        private string name;
        private string databasename;
        private int count;
        private int max;
        private int min;
        private int avg;

        public string Name
        {
            get
            {
                return name;
            }
            set
            {
                name = value;
            }
        }

        public string DatabaseName
        {
            get
            {
                return databasename;
            }
            set
            {
                databasename = value;
            }
        }

        public int Count
        {
            get
            {
                return count;
            }
            set
            {
                count = value;
            }
        }

        public int Max
        {
            get
            {
                return max;
            }
            set
            {
                max = value;
            }
        }

        public int Min
        {
            get
            {
                return min;
            }
            set
            {
                min = value;
            }
        }

        public int Avg
        {
            get
            {
                return avg;
            }
            set
            {
                avg = value;
            }
        }
    }

    class WorkflowPostAnalysis
    {        
        DateTime m_startTime;        
        ArrayList m_sqlServerCNN;
        string m_prefix;
        
        ArrayList m_organizations;

        public ArrayList Organizations
        {
            get
            {
                return m_organizations;
            }
        }
        Hashtable workflows;        

        public void Start()
        {
            for (int i = 0; i < m_sqlServerCNN.Count; i++)
            {
                string databasename = (string)m_organizations[i] + "_MSCRM";

                Console.WriteLine("Moving AsyncOperationbase table for {0}", databasename);
                MoveAsyncTableToMaster((string)m_sqlServerCNN[i],databasename);
            }
        }

        public void MoveAsyncTableToMaster(string sqlServerCNN, string databaseName)
        {
            SqlConnection sqlConnection = null;
            try
            {
                sqlConnection = new SqlConnection(sqlServerCNN);

                try
                {
                    sqlConnection.Open();
                }
                catch (Exception e)
                {
                    System.Diagnostics.Debug.WriteLine(e.Message);                    
                }

                try
                {
                    // Generate the Sql command to set the database to Full Restore
                    SqlCommand sqlCommand = new SqlCommand();
                    sqlCommand.Connection = sqlConnection;
                    sqlCommand.CommandText = "select * into master.." + m_prefix + "_" + databaseName + " from asyncoperationbase";
                    sqlCommand.CommandTimeout = 0;
                    sqlCommand.CommandType = System.Data.CommandType.Text;
                    sqlCommand.ExecuteNonQuery();
                    Console.WriteLine("Created " + m_prefix + "_" + databaseName);
                }
                catch (Exception e)
                {
                    System.Diagnostics.Debug.WriteLine(e.Message);
                }
            }
            catch (Exception e)
            {
                System.Diagnostics.Debug.WriteLine(e.Message);
            }
            finally
            {
                if (sqlConnection != null)
                {
                    sqlConnection.Close();
                }
            }
        }

        public void RetrieveTables()
        {

            SqlConnection sqlConnection = null;
            try
            {
                SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder();
                builder.ConnectionString = (string)m_sqlServerCNN[0];
                builder.InitialCatalog = "MASTER";
                builder.IntegratedSecurity = true;

                string connString = builder.ConnectionString;
                sqlConnection = new SqlConnection(connString);

                try
                {
                    sqlConnection.Open();
                }
                catch (Exception e)
                {
                    System.Diagnostics.Debug.WriteLine(e.Message);
                }

                try
                {
                    // Generate the Sql command to set the database to Full Restore
                    SqlCommand sqlCommand = new SqlCommand();
                    sqlCommand.Connection = sqlConnection;
                    sqlCommand.CommandText = @"select name as tablename from master..sysobjects 
                                                    where 
	                                                    xtype='u'
	                                                    and
	                                                    name like '" + m_prefix + @"%'";
                    sqlCommand.CommandTimeout = 0;
                    sqlCommand.CommandType = System.Data.CommandType.Text;
                    SqlDataReader results = sqlCommand.ExecuteReader();

                    ArrayList tableNameList = new ArrayList();

                    while (results.Read())
                    {
                        tableNameList.Add(results[0].ToString());
                    }
                    if (results != null)
                    {
                        results.Close();
                    }

                    for (int i = 0; i < tableNameList.Count; i++)
                    {
                        string dbName = (tableNameList[i].ToString()).Substring(m_prefix.Length + 1);
                        m_startTime = m_startTime + TimeSpan.FromHours(8);
                        string startTime = m_startTime.Year.ToString() + "-" + m_startTime.Month.ToString() + "-" + m_startTime.Day.ToString() + " " + m_startTime.Hour.ToString() + ":" + m_startTime.Minute.ToString() + ":" + m_startTime.Second.ToString() + "." + m_startTime.Millisecond.ToString();
                        
                        SqlCommand sqlCommand2 = new SqlCommand();
                        sqlCommand2.Connection = sqlConnection;
                        sqlCommand2.CommandText = @"select name, min(datediff(second ,startedon, completedon)) as [min],
                                max(datediff(second ,startedon, completedon))as [max], 
                                avg(datediff(second ,startedon, completedon)) as [avg], 
                                count(*) as [count] 
                                from " + m_prefix + @"_" + dbName +
                                @" where startedon > '" + startTime + @"'                                
                                group by name";

                        sqlCommand2.CommandTimeout = 0;
                        sqlCommand2.CommandType = System.Data.CommandType.Text;
                        SqlDataReader results2 = sqlCommand2.ExecuteReader();

                        while (results2.Read())
                        {
                            WorkflowInfo workflowInfo = new WorkflowInfo();

                            if (!results2.IsDBNull(0))
                            {
                                workflowInfo.Name = (string)results2["name"];
                            }
                            else
                            {
                                workflowInfo.Name = "<NULL>";
                            }

                            workflowInfo.DatabaseName = dbName;
                            if (!results2.IsDBNull(1))
                            {
                                workflowInfo.Min = int.Parse(results2["min"].ToString());
                            }
                            else
                            {
                                workflowInfo.Min = -1;
                            }

                            if (!results2.IsDBNull(2))
                            {
                                workflowInfo.Max = int.Parse(results2["max"].ToString());
                            }
                            else
                            {
                                workflowInfo.Max = -1;
                            }

                            if (!results2.IsDBNull(3))
                            {
                                workflowInfo.Avg = int.Parse(results2["avg"].ToString());
                            }
                            else
                            {
                                workflowInfo.Avg = -1;
                            }
                                                        
                            workflowInfo.Count = int.Parse(results2["count"].ToString());

                            if (workflows.ContainsKey(workflowInfo.Name))
                            {
                                Hashtable list = (Hashtable)workflows[workflowInfo.Name];
                                if (list.ContainsKey(dbName))
                                {
                                    list[dbName] = workflowInfo;
                                }
                                else
                                {
                                    list.Add(dbName, workflowInfo);
                                }
                                workflows[workflowInfo.Name] = list;
                            }
                            else
                            {
                                Hashtable list = new Hashtable();
                                list.Add(workflowInfo.DatabaseName, workflowInfo);
                                workflows.Add(workflowInfo.Name, list);
                            }
                        }
                        if (results2 != null)
                        {
                            results2.Close();
                        }
                    }
                }
                catch (Exception e)
                {
                    System.Diagnostics.Debug.WriteLine(e.Message);
                }
            }
            catch (Exception e)
            {
                System.Diagnostics.Debug.WriteLine(e.Message);
            }
            finally
            {
                if (sqlConnection != null)
                {
                    sqlConnection.Close();
                }
            }

        }

        public void CreateLog()
        {
            int total_Count = 0;
            float total_Avg = 0;

            using (StreamWriter sw = new StreamWriter(m_prefix + ".csv"))
            {
                sw.Write("NAME :\t");
                for (int i = 0; i < m_organizations.Count; i++)
                {
                        string dbname = (string)m_organizations[i] + "_MSCRM";
                        sw.Write(" {0}, Count, Avg, Min, Max: \t", dbname);
                }
                sw.WriteLine(" Total_Count, Total_Avg, Average: \t");
                foreach (DictionaryEntry de in workflows)
                {
                    total_Count = 0;
                    total_Avg = 0;
                    sw.Write(de.Key.ToString() + ":\t");

                    Hashtable list = (Hashtable)de.Value;
                                        
                    for (int i = 0; i < m_organizations.Count; i++)
                    {
                            string dbname = (string)m_organizations[i] + "_MSCRM";

                            WorkflowInfo workflowInfo = (WorkflowInfo)list[dbname];

                            if (workflowInfo != null)
                            {
                                if (workflowInfo.Avg != -1)
                                {
                                    sw.Write("\t {0}, {1}, {2}, {3} :\t", workflowInfo.Count, workflowInfo.Avg, workflowInfo.Min, workflowInfo.Max);
                                    total_Count += workflowInfo.Count;
                                    total_Avg += workflowInfo.Avg;
                                }
                                else
                                {
                                    sw.Write("\t {0}, NIL, NIL, NIL :\t", workflowInfo.Count, workflowInfo.Avg, workflowInfo.Min, workflowInfo.Max);
                                }
                            }
                            else
                            {
                                sw.Write("\t -, -, -, - :\t ");
                            }
                    }
                    sw.WriteLine(" {0}, {1}, {2} ", total_Count, total_Avg, total_Avg / m_organizations.Count);
                }
            }
        }


        public WorkflowPostAnalysis(int runduration, string loadtestname)
        {
            string configDirKeyPath = "SOFTWARE\\Microsoft\\MSCRM";
            string configDir = null;

            if (Registry.LocalMachine.OpenSubKey(configDirKeyPath) != null)
            {
                RegistryKey regKey = Registry.LocalMachine.OpenSubKey(configDirKeyPath);
                configDir = (string)regKey.GetValue("CRM_Perf_Toolkit_ConfigDir", "c:\\crmstress");
            }
            else
            {
                //setting the default directory of configsettings.xml to c:\crmstress folder
                configDir = "c:\\crmstress";
            }

            XmlDocument configSettings = new XmlDocument();
            configSettings.Load(configDir + "\\configsettings.xml");

            XmlNode root = configSettings.DocumentElement;

            XmlNode crmservers = root.SelectSingleNode("crmservers");

            XmlNodeList crmserverList = crmservers.SelectNodes("crmserver");

            m_organizations = new ArrayList();
            m_sqlServerCNN = new ArrayList();

            for (int i = 0; i < crmserverList.Count; i++)
            {
                XmlNode org = crmserverList[i].SelectSingleNode("organization");
                if(org != null)
                {
                    if (org.Attributes["name"] != null)
                    {
                        m_organizations.Add(org.Attributes["name"].Value);
                    }
                }

                XmlNode sqlcnn = crmserverList[i].SelectSingleNode("sqlcnn");
                if(sqlcnn != null)
                {
                    if (sqlcnn.Attributes["value"] != null)
                    {
                        m_sqlServerCNN.Add(sqlcnn.Attributes["value"].Value);
                    }
                }
            }
            m_startTime = DateTime.Now;
            m_prefix = "WorkfowStats_" + loadtestname + DateTime.Now.ToString();
            m_prefix = m_prefix.Replace(" ", "_");
            m_prefix = m_prefix.Replace("/", "_");
            m_prefix = m_prefix.Replace(":", "_");
            workflows = new Hashtable();
        }
    }
}
